from typing import Optional
from application import BasicException
from application.enumeration.StatusCodeEnum import StatusCodeEnum
from application.mapper.FollowMapper import FollowMapper
from application.mapper.NoteMapper import NoteMapper
from application.mapper.UserMapper import UserMapper
from application.model.FollowModel import FollowModel
from application.model.UserModel import UserModel
from application.entity.UserEntity import UserSearchOut


async def follow_user(user_model: UserModel, follower_id: int) -> None:
    """
    关注用户
    :param user_model: 当前用户ORM模型
    :param follower_id: 关注用户ID
    :return:
    """
    user_id: int = user_model.id  # 用户ID（粉丝）
    # 判断是否关注自己
    if user_id == follower_id:
        raise BasicException(status_code=StatusCodeEnum.ALREADY_EXIST_ERROR.value, message="不能操作自己！")
    # 如果被关注用户是否存在或已被禁用
    follower_model: UserModel = await UserMapper.get_data_by_id(data_id=follower_id)
    if follower_model is None:
        raise BasicException(status_code=StatusCodeEnum.NOT_FOUND_ERROR.value, message="关注用户不存在！")
    if follower_model.is_disabled:
        raise BasicException(status_code=StatusCodeEnum.HIDE_ERROR.value, message="关注用户已被禁用！")
    # 判断是否已经关注
    if await FollowMapper.get_info_by_follow_and_fans(follower_id=follower_id, followee_id=user_id) is not None:
        raise BasicException(status_code=StatusCodeEnum.ALREADY_EXIST_ERROR.value, message="已经关注过该用户了！")
    # 记录关注
    result = await FollowMapper.insert(data={
        "follower_id": follower_id,
        "followee_id": user_id
    })
    if not result:
        raise BasicException(status_code=StatusCodeEnum.ERROR.value, message="关注失败，请稍后再试！")


async def cancel_follow(follower_id: int, user_model: UserModel) -> None:
    """
    取消关注用户
    :param follower_id: 关注用户ID
    :param user_model: 当前用户ORM模型（粉丝）
    :return:
    """
    user_id: int = user_model.id
    if follower_id == user_id:
        raise BasicException(status_code=StatusCodeEnum.ERROR.value, message="不能操作自己！")
    follow_model: Optional[FollowModel] = await FollowMapper.get_info_by_follow_and_fans(follower_id=follower_id,
                                                                                         followee_id=user_id)
    if follow_model is None:
        raise BasicException(StatusCodeEnum.NOT_FOUND_ERROR.value, message="未关注该用户！")
    if not await FollowMapper.delete(orm_model=follow_model):
        raise BasicException(status_code=StatusCodeEnum.ERROR.value, message="取消关注失败，请稍后再试！")


async def get_fans_by_user_id(user_id: int, page: int, page_size: int) -> list[Optional[UserSearchOut]]:
    """
    根据用户ID获取粉丝列表
    :param user_id: 用户ID
    :param page: 当前页
    :param page_size: 每页条数
    :return: 粉丝列表
    """
    # 获取粉丝ID列表
    follow_model_list: list[Optional[FollowModel]] = await FollowMapper.get_data_list(page=page, page_size=page_size,
                                                                                      follower_id=user_id)
    fans_list: list = []
    # 遍历获取粉丝信息
    for follow_model in follow_model_list:
        user_model: UserModel = await UserMapper.get_data_by_id(data_id=follow_model.follower_id)
        user_out: UserSearchOut = UserSearchOut(**user_model.to_dict())
        user_out.fans_num = await FollowMapper.orm_model.filter(follower_id=user_model.id).count()  # 粉丝数
        user_out.follow_num = await FollowMapper.orm_model.filter(followee_id=user_model.id).count()  # 关注数
        user_out.note_num = await NoteMapper.orm_model.filter(user_id=user_model.id).count()  # 帖子数量
        fans_list.append(user_out)
    return fans_list


async def get_follows_by_user_id(user_id: int, page: int, page_size: int) -> list[Optional[UserSearchOut]]:
    """
    根据用户ID获取关注列表
    :param user_id: 用户ID
    :param page: 当前页
    :param page_size: 每页条数
    :return: 关注者列表
    """
    # 获取粉丝ID列表
    follow_model_list: list[Optional[FollowModel]] = await FollowMapper.get_data_list(page=page, page_size=page_size,
                                                                                      followee_id=user_id)
    follow_list: list = []
    # 遍历获取粉丝信息
    for follow_model in follow_model_list:
        user_model: UserModel = await UserMapper.get_data_by_id(data_id=follow_model.follower_id)
        user_out: UserSearchOut = UserSearchOut(**user_model.to_dict())
        user_out.fans_num = await FollowMapper.orm_model.filter(follower_id=user_model.id).count()  # 粉丝数
        user_out.follow_num = await FollowMapper.orm_model.filter(followee_id=user_model.id).count()  # 关注数
        user_out.note_num = await NoteMapper.orm_model.filter(user_id=user_model.id).count()  # 帖子数量
        follow_list.append(user_out)
    return follow_list
